#include <iostream>
#include <vector>

// 表达式模板基类
template<typename E>
class VecExpression {
public:
    // 重载操作符[]：获取表达式中的元素
    double operator[](size_t i) const { return static_cast<const E&>(*this)[i]; }
    
    // 返回表达式的大小
    size_t size() const { return static_cast<const E&>(*this).size(); }
};

// 向量类模板
template<typename T>
class Vector : public VecExpression<Vector<T>> {
    std::vector<T> elems;

public:
    // 构造函数：构造指定大小的向量
    Vector(size_t n) : elems(n) {}
    
    // 构造函数：从初始化列表构造向量
    Vector(std::initializer_list<T> init) : elems(init) {}

    // 构造函数：从任意 VecExpression 对象构造向量
    template<typename E>
    Vector(const VecExpression<E>& vec) {
        elems.resize(vec.size());
        for (size_t i = 0; i != vec.size(); ++i) {
            elems[i] = vec[i];
        }
    }

    // 返回向量的大小
    size_t size() const { return elems.size(); }
    
    // 重载操作符[]：获取向量中的元素（const 和非 const 版本）
    T operator[](size_t i) const { return elems[i]; }
    T& operator[](size_t i) { return elems[i]; }

    // 赋值运算符：从任意 VecExpression 对象赋值给向量
    template<typename E>
    Vector& operator=(const VecExpression<E>& expr) {
        if (this->size() != expr.size()) {
            elems.resize(expr.size());
        }
        for (size_t i = 0; i < expr.size(); i++) {
            elems[i] = expr[i];
        }
        return *this;
    }
};

// 表达式模板：两个向量的和
template<typename E1, typename E2>
class VecSum : public VecExpression<VecSum<E1, E2>> {
    const E1& u;
    const E2& v;

public:
    // 构造函数：接受两个表达式对象
    VecSum(const E1& u, const E2& v) : u(u), v(v) {}

    // 返回表达式的大小
    size_t size() const { return u.size(); }
    
    // 重载操作符[]：计算两个表达式中对应元素的和
    double operator[](size_t i) const { return u[i] + v[i]; }
};

// 操作符重载：两个表达式对象的和
template<typename E1, typename E2>
VecSum<E1, E2> operator+(const VecExpression<E1>& u, const VecExpression<E2>& v) {
    return VecSum<E1, E2>(static_cast<const E1&>(u), static_cast<const E2&>(v));
}

int main() {
    // 创建两个向量对象
    Vector<double> v = {1.0, 2.0, 3.0};
    Vector<double> w = {4.0, 5.0, 6.0};
    
    // 使用表达式模板进行向量相加
    Vector<double> x = v + w;

    // 输出结果
    for (size_t i = 0; i < x.size(); i++) {
        std::cout << x[i] << ' ';
    }
    std::cout << std::endl;

    return 0;
}
